package com.yonyou.ucf.mdf.app.controller.isv;

import com.alibaba.fastjson.JSON;
import com.yonyou.ucf.mdd.common.model.rule.RuleExecuteResult;
import com.yonyou.ucf.mdd.ext.api.IBillService;
import com.yonyou.ucf.mdd.ext.bill.dto.BillDataDto;
import com.yonyou.ucf.mdd.ext.core.AppContext;
import com.yonyou.ucf.mdf.app.common.ResultMessage;
import com.yonyoucloud.iuap.ucf.mdd.starter.ucg.openapi.isv.router.module.InnerRequestParamBO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.entity.ContentType;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping(InnerController.PATH_INNER_PREFIX)
public class InnerController {

    private final IBillService billService;

    public static final String PATH_INNER_PREFIX = "/rest/v1/abpaas/isv/inner";

    @RequestMapping(value = "/billcode", method = RequestMethod.POST)
    public void handleInnerBillCodeRequest(
            @RequestBody InnerRequestParamBO innerRequestParamBO,
            HttpServletRequest request,
            HttpServletResponse httpResponse)
            throws Exception {
        Map<String, String> iuapContext = innerRequestParamBO.getIuapContext();
        String className = innerRequestParamBO.getClassName();
        String methodName = innerRequestParamBO.getMethodName();
        List<String> params = innerRequestParamBO.getParams();
        List<String> paramTypes = innerRequestParamBO.getParamTypes();
        if (iuapContext != null) {
            // buildBillCodeContext(iuapContext);
        }

        int size = params.size();
        Class<?>[] classes = new Class[size];
        Object[] objects = new Object[size];
        for (int i = 0; i < size; i++) {
            String paramType = paramTypes.get(i);
            Class<?> clazz = ClassUtils.getClass(paramType, false);
            classes[i] = clazz;
            objects[i] = JSON.parseObject(params.get(i), clazz);
        }
        String[] classNameSplit = className.split("\\.");
        int length = classNameSplit.length;

        Object objectClass = AppContext.getBean(classNameSplit[length - 1]);
        if (objectClass == null) {
            String errorMessage = className + " not a specified interface";
            log.error(errorMessage);
            throw new Exception(errorMessage);
        }
        Method method = objectClass.getClass().getMethod(methodName, classes);
        Object resultObject = method.invoke(objectClass, objects);
        httpResponse.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
        renderJson(httpResponse, ResultMessage.data(resultObject));
    }

    /** 根据请求体中的用户信息设置上下文用户信息 */
  /*private void buildBillCodeContext(Map<String, String> iuapContext) {
      String tenantId = iuapContext.get(TENANT_ID);
      String userId = iuapContext.get(USER_ID);
      TokenResult tempToken = authApi.generateToken(tenantId, userId);
      if (tempToken != null) {
          String yhtAccessToken = tempToken.getToken();
          CommonAuthResult commonAuthResult = new CommonAuthResult(tenantId, userId);
          //ISVBuildContextUtil.buildContext(commonAuthResult, yhtAccessToken, "");
      }
  }*/

    @RequestMapping("/bill/detail")
    public void detail(
            String billnum,
            String id,
            @RequestParam(required = false) String terminalType,
            HttpServletRequest request,
            HttpServletResponse response) {
        try {
            BillDataDto bill = new BillDataDto();
            bill.setBillnum(billnum);
            bill.setId(id + "");
            bill.setTenantId(AppContext.getTenantId());
            bill.setUserId(AppContext.getThreadContext("userId"));
            bill.setTerminalType(terminalType);
            // 实现实体延迟加载功能
            String dataKeys = request.getParameter("entityKeys");
            if (StringUtils.isNotBlank(dataKeys)) {
                bill.setLoadDataEntityKeys(new ArrayList<>(Arrays.asList(dataKeys.split(","))));
            }
            Map map = billService.detail(bill);
            response.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
            renderJson(response, ResultMessage.data(map));
        } catch (Exception e) {
            response.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
            renderJson(response, ResultMessage.error(e.getMessage()));
            log.error("exception when query bill detail", e);
        }
    }

    @RequestMapping("/bill/save")
    public void save(
            @RequestBody BillDataDto bill, HttpServletRequest request, HttpServletResponse response) {
        executeData(bill, false, request, response);
    }

    private void executeData(
            BillDataDto bill,
            boolean isHoldNull,
            HttpServletRequest request,
            HttpServletResponse response) {
        try {
            String action = Thread.currentThread().getStackTrace()[2].getMethodName();
            RuleExecuteResult result = billService.executeUpdate(action, bill);
            response.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
            renderJson(
                    response, com.yonyou.ucf.mdd.ext.util.ResultMessage.data(result.getData(), isHoldNull));
        } catch (Exception e) {
            response.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
            renderJson(response, com.yonyou.ucf.mdd.ext.util.ResultMessage.error(e.getMessage()));
            log.error("executeData异常: ", e);
        }
    }

    private void renderJson(HttpServletResponse response, String json) {
        response.setCharacterEncoding(Consts.UTF_8.name());
        response.setContentType(ContentType.APPLICATION_JSON.getMimeType());
        try {
            // the max age policy to renew CORS check. Here it's 14 days long
            response.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
            response.getWriter().write(json);
        } catch (IOException e) {
            log.error("exception when render json", e);
        }
    }
}
